package vectors;
import junit.framework.TestCase;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import vectors.Vector;


public class VectorTest extends TestCase{

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testVector() {
		fail("Not yet implemented");
	}

	@Test
	public void testToString() {
		fail("Not yet implemented");
	}

	@Test
	public void testPlusDouble() {
		fail("Not yet implemented");
	}

	@Test
	public void testPlusVector() {
		fail("Not yet implemented");
	}

	@Test
	public void testMinus() {
		fail("Not yet implemented");
	}

	@Test
	public void testTimesDouble() {
		fail("Not yet implemented");
	}

	@Test
	public void testTimesVector() {
		fail("Not yet implemented");
	}

	@Test
	public void testDot() {
		fail("Not yet implemented");
	}

	@Test
	public void testDivideDouble() {
		fail("Not yet implemented");
	}

	@Test
	public void testDivideVector() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetNOD() {
		double[] vals = {0.005, 250, -11.1, 0.0, 1.0, -1.000006};
		Vector vec = new Vector(vals);
		assertEquals("Number of dimensions do not match length of value array", vec.getNOD(), vals.length );
	}

	@Test
	public void testRandomVals() {
		//fail("Not yet implemented");
	}

	@Test
	public void testRandom() {
		//fail("Not yet implemented");
	}

	@Test
	public void testZero() {
		Vector exp;
		Vector act;
		double[] vals1 = {0,0,0,0,0};
		exp = new Vector(vals1);
		act = Vector.zero(5);
		assertTrue(act.equals(exp));
		
		double[] vals2 = {0};
		exp = new Vector(vals2);
		act = Vector.zero(1);
		assertTrue(act.equals(exp));
		
		double[] vals3 = new double[10000];
		for(int i=0;i<10000;i++){
			vals3[i] = 0;
		}
		exp = new Vector(vals3);
		act = Vector.zero(10000);
		assertTrue(act.equals(exp));
	}
	
	@Test
	public void testUnit() {
		Vector exp;
		Vector act;
		double[] vals1 = {0,0,1,0,0};
		exp = new Vector(vals1);
		act = Vector.unit(5,2);
		assertTrue(act.equals(exp));
		
		double[] vals2 = {0,0,0,1};
		exp = new Vector(vals2);
		act = Vector.unit(4,3);
		assertTrue(act.equals(exp));
		
		double[] vals3 = {1};
		exp = new Vector(vals3);
		act = Vector.unit(1,0);
		assertTrue(act.equals(exp));
	}

	@Test
	public void testGetLength() {
		double[] vals1 = {0.005, 250, -11.1, 0.0, 1.0, -1.000006};
		Vector vec1 = new Vector(vals1);
		assertEquals("Vector doesn't have correct length squared", 250.25029477904723539123075921198, vec1.getLength(), 250.25029477904723539123075921198*0.000000001);
		double[] vals2 = {0.0, 0.0};
		Vector vec2 = new Vector(vals2);
		assertEquals("Vector doesn't have correct length squared", 0.0, vec2.getLength(), Double.MIN_EXPONENT);
	}

	@Test
	public void testGetLengthSq() {
		double[] vals1 = {0.01, 450, -11, 0.0, 1.0, -1.000009};
		Vector vec1 = new Vector(vals1);
		assertEquals("Vector doesn't have correct length squared", 202623.000118000081, vec1.getLengthSq(), 202623.000118000081*0.000000001);
		double[] vals2 = {0.0, 0.0};
		Vector vec2 = new Vector(vals2);
		assertEquals("Vector doesn't have correct length squared", 0.0, vec2.getLengthSq(), Double.MIN_EXPONENT);
	}

	@Test
	public void testNormalize() {
		double[] vals = {1.8, 4565, 0.000234, 0.0, 1.0};
		Vector vec = new Vector(vals);
		assertEquals("Normalized Vector doesn't have length of exactly 1", 1.0, vec.normalize().getLength(), 0.000000001);
		Vector zero = Vector.zero(4);
		assertEquals("Normalized Vector doesn't have length of exactly 1", 1.0, zero.normalize().getLength(), 0.000000001);
		//TODO: Should also check that direction is approximately the same by using Direction, then checking the cosine between the two. But keep in mind the zero vector
	}
	
	@Test
	//TODO: Unit vector test should be in a combinationTests file or something
	public void testGenerateDirection() {
		// Test single direction vectors
		int dimsToTest = 5;
		for(int i=0;i<dimsToTest;i++){
			Vector vec = Vector.unit(dimsToTest, i);
			Vector newVec = vec.generateDirection().generateUnitVector();
			for(int j=0;j<dimsToTest;j++){
				assertEquals("Direction is not correct for value "+j+". Returned Vector: "+newVec, newVec.getValue(j), vec.getValue(j), 0.000000001);
			}
		}
		// Test 2d -> circle
		fail("Not implemented");
		// Test negative, zero, and one dimension
		fail("Not implemented");
		// Test some complex direction
		fail("Not implemented");
	}

}
